`timescale 1ns / 1ps

// FIR滤波器模块
module FIR(
    // FIR滤波器接口定义
        input clk,                       // 时钟信号
        input reset,                     // 复位信号
        input signed [15:0] s_axis_fir_tdata, // 输入数据
        input [3:0] s_axis_fir_tkeep,   // 输入数据保持信号
        input s_axis_fir_tlast,          // 输入数据最后一个标志
        input s_axis_fir_tvalid,         // 输入数据有效标志
        input m_axis_fir_tready,         // 输出数据准备接收标志
        output reg m_axis_fir_tvalid,    // 输出数据有效标志
        output reg s_axis_fir_tready,    // 输入数据准备接收标志
        output reg m_axis_fir_tlast,      // 输出数据最后一个标志
        output reg [3:0] m_axis_fir_tkeep, // 输出数据保持信号
        output reg signed [31:0] m_axis_fir_tdata // 输出数据
    );


    // 更新输出keep信号
    always @ (posedge clk)
        begin
            m_axis_fir_tkeep <= 4'hf;
        end
        
    // 更新输出last信号
    // 在时钟上升沿时的行为
    always @ (posedge clk)
        begin
            // 检查输入信号s_axis_fir_tlast的状态
            if (s_axis_fir_tlast == 1'b1)
                begin
                    // 当s_axis_fir_tlast为1时，输出m_axis_fir_tlast为1
                    m_axis_fir_tlast <= 1'b1;
                end
            else
                begin
                    // 否则，输出m_axis_fir_tlast为0
                    m_axis_fir_tlast <= 1'b0;
                end
        end
    
    // 15-tap FIR 
    reg enable_fir, enable_buff;
    reg [3:0] buff_cnt;
    reg signed [15:0] in_sample; 
    reg signed [15:0] buff0, buff1, buff2, buff3, buff4, buff5, buff6, buff7, buff8, buff9, buff10, buff11, buff12, buff13, buff14; 
    wire signed [15:0] tap0, tap1, tap2, tap3, tap4, tap5, tap6, tap7, tap8, tap9, tap10, tap11, tap12, tap13, tap14; 
    reg signed [31:0] acc0, acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10, acc11, acc12, acc13, acc14; 

    
    /* Taps for LPF running @ 1MSps with a cutoff freq of 400kHz*/
    // 该段代码用于定义FIR滤波器的系数
    // 这些系数是经过计算得出的，以便在滤波过程中使用
    assign tap0 = 16'hFC9C;  // twos(-0.0265 * 32768) = 0xFC9C
    assign tap1 = 16'h0000;  // 0
    assign tap2 = 16'h05A5;  // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
    assign tap3 = 16'h0000;  // 0
    assign tap4 = 16'hF40C;  // twos(-0.0934 * 32768) = 0xF40C
    assign tap5 = 16'h0000;  // 0
    assign tap6 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
    assign tap7 = 16'h4000;  // 0.5000 * 32768 = 16384 = 0x4000
    assign tap8 = 16'h282D;  // 0.3139 * 32768 = 10285.8752 = 10285 = 0x282D
    assign tap9 = 16'h0000;  // 0
    assign tap10 = 16'hF40C; // twos(-0.0934 * 32768) = 0xF40C
    assign tap11 = 16'h0000; // 0
    assign tap12 = 16'h05A5; // 0.0441 * 32768 = 1445.0688 = 1445 = 0x05A5
    assign tap13 = 16'h0000; // 0
    assign tap14 = 16'hFC9C; // twos(-0.0265 * 32768) = 0xFC9C
    
    /* This loop sets the tvalid flag on the output of the FIR high once 
    /* 
    模块功能：实现一个循环缓冲区，用于存储输入样本并管理样本处理的使能信号和计数。
    该模块在复位条件后首次填充输入样本到循环缓冲区，并在相应条件下更新状态。
    */
        always @ (posedge clk or negedge reset)
            begin
                // 此块代码用于处理复位逻辑，在复位状态下初始化相关信号
                if (reset == 1'b0) //if (reset == 1'b0 || tvalid_in == 1'b0)
                    begin
                        buff_cnt <= 4'd0;
                        enable_fir <= 1'b0;
                        in_sample <= 8'd0;
                    end
                // 处理 FIR 的输出就绪信号和输入有效信号
                else if (m_axis_fir_tready == 1'b0 || s_axis_fir_tvalid == 1'b0)
                    begin
                        // 禁用 FIR 计算
                        enable_fir <= 1'b0;
                        // 重置缓冲计数器
                        buff_cnt <= 4'd15;
                        // 保持输入样本不变
                        in_sample <= in_sample;
                    end
                // 判断缓冲计数器是否达到15
                else if (buff_cnt == 4'd15)
                    begin
                        // 复位缓冲计数器，启动 FIR 处理
                        buff_cnt <= 4'd0;
                        enable_fir <= 1'b1;
                        in_sample <= s_axis_fir_tdata;
                    end
                else
                    begin
                        // 增加缓冲计数器，继续接收输入样本
                        buff_cnt <= buff_cnt + 1;
                        in_sample <= s_axis_fir_tdata;
                    end
            end

    // 更新输入ready和输出valid信号
    always @ (posedge clk)
        begin
            // 处理 FIR 滤波器的输出信号的逻辑
            // ?如果复位信号为低，或主轴承FIFO的就绪信号为低，或从轴承FIFO的有效信号为低，则禁用准备信号和有效信号
                if(reset == 1'b0 || m_axis_fir_tready == 1'b0 || s_axis_fir_tvalid == 1'b0)
                    begin
                        s_axis_fir_tready <= 1'b0;
                        m_axis_fir_tvalid <= 1'b0;
                        enable_buff <= 1'b0;
                    end
            else
                begin
                    s_axis_fir_tready <= 1'b1;
                    m_axis_fir_tvalid <= 1'b1;
                    enable_buff <= 1'b1;
                end
        end
    
    /* Circular buffer bring in a serial input sample stream that 
     * creates an array of 15 input samples for the 15 taps of the filter.  
     * 此部分代码实现了一个循环缓冲区，接收串行输入样本流， 
     * 创建一个包含15个输入样本的数组，用于滤波器的15个抽头。*/
    always @ (posedge clk)
        begin
            if(enable_buff == 1'b1)

    // Add your code here
                begin
                    // 依次将之前的样本向后移动
                    buff14 <= buff13;
                    buff13 <= buff12;
                    buff12 <= buff11;
                    buff11 <= buff10;
                    buff10 <= buff9;
                    buff9  <= buff8;
                    buff8  <= buff7;
                    buff7  <= buff6;
                    buff6  <= buff5;
                    buff5  <= buff4;
                    buff4  <= buff3;
                    buff3  <= buff2;
                    buff2  <= buff1;
                    buff1  <= buff0;
                    buff0  <= in_sample; // 新样本进入缓冲区
                end
        end
        
    /* Multiply stage of FIR */
    /* FIR乘法阶段 */
    always @ (posedge clk)
        begin
            if (enable_fir == 1'b1)

    // Add your code here
    // 该代码块用于将多个累加器的值相加，并将结果赋值给 m_axis_fir_tdata
    // 这个计算可能是在一个 FIR 滤波器的数据处理过程中进行的
                begin
                    acc0  <= buff0 * tap0;
                    acc1  <= buff1 * tap1;
                    acc2  <= buff2 * tap2;
                    acc3  <= buff3 * tap3;
                    acc4  <= buff4 * tap4;
                    acc5  <= buff5 * tap5;
                    acc6  <= buff6 * tap6;
                    acc7  <= buff7 * tap7;
                    acc8  <= buff8 * tap8;
                    acc9  <= buff9 * tap9;
                    acc10 <= buff10 * tap10;
                    acc11 <= buff11 * tap11;
                    acc12 <= buff12 * tap12;
                    acc13 <= buff13 * tap13;
                    acc14 <= buff14 * tap14;
                end
        end    
        
     /* Accumulate stage of FIR */
     /* FIR滤波器的累加阶段 */   
    always @ (posedge clk) 
        begin
            if (enable_fir == 1'b1)
                
    // Add your code here
                // 该代码块用于将多个累加器的值相加，并将结果赋值给 m_axis_fir_tdata
                // 这个计算可能是在一个 FIR 滤波器的数据处理过程中进行的
                begin
                    m_axis_fir_tdata <= acc0 + acc1 + acc2 + acc3 + acc4 +
                                        acc5 + acc6 + acc7 + acc8 + acc9 +
                                        acc10 + acc11 + acc12 + acc13 + acc14;
                end
        end     

endmodule